/*
 * Copyright (c) 2010 Olivier Van Acker
 *
 * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
 */

package org.transformatorhuis.unix.server;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.logging.Logger;

/**
 * User: Olivier Van Acker <cyberroadie@transformatorhuis.net>
 * Date: Mar 11, 2010
 */
public class CloneableServer extends AbstractServer {

    Logger logger = Logger.getLogger(CloneableServer.class.getName());

    private boolean isSerialized = false;

    /**
     * Default constructor
     *
     * @param args          server arguments (pass from main(args)
     * @param processThread thread to be cloned and started
     * @throws Exception
     */
    public CloneableServer(String[] args, Cloneable processThread) {
        instantiate(args, processThread);
    }


    /**
     * Runs the server
     *
     * @param forks             how many times to JVM needs to be forked
     * @param threadsPerProcess how many threads to be cloned per forked JVM
     * @throws IOException
     */
    @Override
    public void run(int forks, int threadsPerProcess) throws IOException {
        String mode = System.getProperty(MODE_PROPERTY);
        if (forks < 1 || threadsPerProcess < 1) {
            syslog.error("Number of forks and number of threads per process needs to be >0");
            syslog.error("Exiting");
            System.exit(-1);
        }
        if (MODE.equals(mode)) {
            syslog.alert("Starting threads");
            try {
                startCloneableThreads(threadsPerProcess);
            } catch (RTFMException e) {
                e.printStackTrace();
                syslog.error("Threads not implemented correctly, can not clone thread");
                System.exit(-1);
            }
        } else {
            syslog.alert("Fork process");
            for (int i = 0; i < forks; i++)
                forkProcess();
        }

    }

    

    

    private void startCloneableThreads(int threadsPerProcess) throws IOException {

//        writePidFile();

        for (int i = 0; i < threadsPerProcess; i++) {
            Observer clonedThread;
            try {
                Method method = processThread.getClass().getMethod("clone", null);
                clonedThread = (Observer) method.invoke(processThread, null);
            } catch (NoSuchMethodException e) {
                throw new RTFMException("Clone method not implemented: " + e.toString());
            } catch (InvocationTargetException e) {
                throw new RTFMException("Error invoking clone method: " + e.toString());
            } catch (IllegalAccessException e) {
                throw new RTFMException("Clone method protected, should be public: " + e.toString());
            }
            if(clonedThread instanceof Observer)
                thSignalHandler.addObserver(clonedThread);
            thread((Runnable) clonedThread, true);
        }

        // hang forever
        Object o = new Object();
        synchronized (o) {
            try {
                o.wait();
            } catch (InterruptedException e) {
                System.exit(0);
            }
        }

    }




}
